package com.example.rabcdemo.service.impl;

import com.example.rabcdemo.annotation.RequestPermission;
import com.example.rabcdemo.entity.Permission;
import com.example.rabcdemo.mapper.PermissionMapper;
import com.example.rabcdemo.service.PermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 权限表 服务实现类
 * </p>
 *
 * @author wuyunbin
 * @since 2023-03-28
 */
@Service
@Slf4j
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    //我们需要解决的问题，怎么对权限做增量修改
    /*
    扫描找出所有的权限
    查数据库，查出所有的已有权限 -> 所有的权限-已有的权限 = 需要新增的权限
     */

    //获取所有的controller里面的所有的方法，读取注解
        /*
        1-我们想干什么？-> 拿到所有的权限更新到数据库中->将来交给前端去显示权限配置页面
        2-我们怎么拿到呢？->扫所有的controller里面的所有的方法，读取自定义注解 ->service下面怎么获取方法呢？
        3-怎么拿？-> handlerMapping.getHandler.Methods() 可以拿到方法
         */

    @Autowired
    private PermissionMapper permissionMapper;

    //handlerMapping.getHandler.Methods() 可以拿到方法
    @Autowired
    private RequestMappingHandlerMapping handlerMapping;

    @Override
    public void reload() {
        //读取数据库获取已有的所有权限
        List<Permission> permissionsInDb = this.list();
        //提前取出数据
        List<String> expressions=new ArrayList<>();
        for (Permission permission : permissionsInDb) {
            expressions.add(permission.getExpression());
        }

        //关键点：扫描所有的controller下面所有的方法
        Map<RequestMappingInfo, HandlerMethod> handlerMethods = handlerMapping.getHandlerMethods();
        //这个methods就是所有的controller下面的所有的方法的集合
        Collection<HandlerMethod> methods = handlerMethods.values();
        for (HandlerMethod value : methods) {
            log.info("{}",value);
        }
        //用来存储新增的权限并提供一次性批量加入数据库，提高存入效率
        List<Permission> newPermissions=new ArrayList<>();

        //遍历所有的方法，拿注解，拿里面的表达式，对比权限，没有就新加入，有就不要理他
        for (HandlerMethod method : methods) {
            //拿注解
            RequestPermission annotation = method.getMethodAnnotation(RequestPermission.class);
            //判断这个方法有没有带RequestPermission注解
            if(annotation!=null){
                //遍历对比 permissionsInDb 跟 我们扫描到的方法注解进行对比
                //数据库中的数据抽取出来的表达式跟当前方法的注解中的表达式不一致，就需要新增存入数据库
                if(!expressions.contains(annotation.expression())){
                    Permission newPermission=new Permission();
                    newPermission.setPermissionName(annotation.name());
                    newPermission.setExpression(annotation.expression());
                    //一旦找到符合条件的新权限，我们就加入到List中，方便后续批量存入
                    newPermissions.add(newPermission);
                }

            }
        }

        //批量存入
        this.saveBatch(newPermissions);

    }
}
